package v1

import (
	"errors"
	"net/http"
	"strconv"
	"zhejianglab/gin-apiserver/model"
	"zhejianglab/gin-apiserver/model/request"

	"github.com/astaxie/beego/validation"
	"github.com/gin-gonic/gin"
)

// UserLogin user login the system
// @Produce  json
// @Tags User
// @Param LoginStruct body request.LoginStruct true "request.LoginStruct"
// @Success 201 {object} gin.H "{"code":201,"msg":"UserLogin successfully!"}"
// @Failure 404 {object} gin.H "{"code":404,"msg":"UserLogin: user name is not exist"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"UserLogin failed!"}"
// @Router /api/v1/user/login [post]
func UserLogin(c *gin.Context) {
	var err error

	var L request.LoginStruct
	_ = c.ShouldBindJSON(&L)
	userName := L.Username
	passWord := L.Password

	valid := validation.Validation{}
	// 校验用户名、密码、的有效性
	valid.Required(userName, "userName").Message("用户名不能为空")
	if valid.HasErrors() {
		err = errors.New("UserLogin: userName is invalid")
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
		return
	}
	valid.Required(passWord, "passWord").Message("密码不能为空")
	if valid.HasErrors() {
		err = errors.New("UserLogin: passWord is invalid")
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
		return
	}

	if userName == "admin" && passWord == "123456" {
		c.JSON(http.StatusCreated, gin.H{"status": http.StatusOK, "message": "UserLogin successfully!", "data": 0})
		return
	}
	if userName == "admin" && passWord != "123456" {
		c.JSON(http.StatusCreated, gin.H{"status": http.StatusInternalServerError, "message": "UserLogin：admin password error!", "data": 0})
		return
	}
	id, ok := model.ExistUserByName(userName)
	if !ok {
		err = errors.New("UserLogin: user name is not exist")
		c.JSON(http.StatusNotFound, gin.H{"status": http.StatusNotFound, "message": err.Error()})
		return
	}
	err = model.UserLogin(userName, passWord)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": "UserLogin: " + err.Error()})
		return
	}
	c.JSON(http.StatusCreated, gin.H{"status": http.StatusOK, "message": "UserLogin successfully!", "data": id})
}

// CreateUser create new user to db
// @Produce  json
// @Tags User
// @Param RegisterStruct body request.RegisterStruct true "request.RegisterStruct"
// @Success 201 {object} gin.H "{"code":201,"msg":"User created successfully!"}"
// @Failure 409 {object} gin.H "{"code":409,"msg":"CreateUser: user name is exist"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"CreateUser failed!"}"
// @Router /api/v1/user [post]
func CreateUser(c *gin.Context) {
	var err error
	var R request.RegisterStruct
	_ = c.ShouldBindJSON(&R)
	userName := R.Username
	passWord := R.Password
	valid := validation.Validation{}

	// 校验用户名、密码、电话号码的有效性
	valid.Required(userName, "userName").Message("用户名不能为空")
	if valid.HasErrors() {
		err = errors.New("CreateUser: userName is invalid")
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
		return
	}
	valid.Required(passWord, "passWord").Message("密码不能为空")
	if valid.HasErrors() {
		err = errors.New("CreateUser: passWord is invalid")
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
		return
	}

	valid.MaxSize(userName, 100, "userName").Message("用户名最长为100字符")
	if _, ok := model.ExistUserByName(userName); ok {
		err = errors.New("CreateUser: user name is exist")
		c.JSON(http.StatusConflict, gin.H{"status": http.StatusConflict, "message": err.Error(), "userName": userName})
		return
	}

	data := model.CreateUser(userName, passWord)
	user, ok := data.(*model.UserInfo)
	if !ok {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": "AddNewJob failed!"})
		return
	}
	c.JSON(http.StatusCreated, gin.H{"status": http.StatusCreated, "message": "User sing up successfully!", "data": user.ID})
}

// GetUser get user info from db
// @Produce  json
// @Tags User
// @Param id path int true "ID"
// @Success 200 {object} gin.H "{"code":200,"msg":"GetUser successfully"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"GetUser failed!"}"
// @Router /api/v1/user/{id} [get]
func GetUser(c *gin.Context) {
	id := c.Param("id")
	data, err := model.GetUser(id)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "message": "User create successfully!", "data": data})
}

// UpdateUser edit user info
// @Produce  json
// @Tags User
// @Param id path int true "ID"
// @Param RegisterStruct body request.RegisterStruct true "request.RegisterStruct"
// @Success 200 {object} gin.H "{"code":200,"msg":"UpdateUser successfully!"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"UpdateUser failed!"}"
// @Router /api/v1/user/{id} [put]
func UpdateUser(c *gin.Context) {
	var err error
	data := make(map[string]interface{})
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
		return
	}
	if !model.ExistUserByID(id) {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": "userID is not exists failed!"})
		return
	}

	var R request.RegisterStruct
	_ = c.ShouldBindJSON(&R)
	userName := R.Username
	passWord := R.Password
	valid := validation.Validation{}

	if userName != "" {
		valid.MaxSize(userName, 100, "userName").Message("用户名最长为100字符")
		data["username"] = userName
	}

	if passWord != "" {
		data["password"] = passWord
	}

	model.UpdateUser(id, data)
	c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "message": "UpdateUser successfully!", "data": data})
	return

}

// DeleteUser delete user info from db
// @Produce  json
// @Tags User
// @Param id path int true "ID"
// @Success 200 {object} gin.H "{"code":200,"msg":"DeleteUser successfully"}"
// @Failure 500 {object} gin.H "{"code":500,"msg":"DeleteUser failed!"}"
// @Router /api/v1/user/{id} [delete]
func DeleteUser(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": err.Error()})
		return
	}

	valid := validation.Validation{}
	valid.Min(id, 1, "id").Message("ID必须大于0")

	if !valid.HasErrors() {
		if model.ExistUserByID(id) {
			model.DeleteUser(id)
			c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "message": "User delete successfully!"})
		} else {
			c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": "User delete failed!"})
			return
		}
	} else {
		c.JSON(http.StatusInternalServerError, gin.H{"status": http.StatusInternalServerError, "message": "id is invalid!"})
		return
	}
}
